home *** CD-ROM | disk | FTP | other *** search
- #1.5
- import BP
-
- d = {}
- ko = "└┴┬├─┼╞╟╚╔╩╦╠═╬╧╤╥╙╘╒╓┘┌█▄▌▀αßΓπΣσµτΦΘΩδ∞φε∩±≥≤⌠⌡÷∙·√ⁿ² ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- ok = "aaaaaaaceeeeiiiinooooouuuuybaaaaaaaceeeeiiiinooooouuuuyyabcdefghijklmnopqrstuvwxyz"
- [d.setdefault(a, b) for a, b in zip(ko, ok)]
- PatternTable = "".join([d.get(chr(i), chr(i)) for i in range(256)])
-
- CIndexes = {}
- CtgPatt = []
-
- def Pattern(v):
- return v.translate(PatternTable, " -.,;:/!?'_=")
-
- def DoIndexCategs():
- global CIndexes, CtgPatt
- CIndexes = {}
- for i, c in enumerate(BP.CategName):
- CIndexes[i] = int(c[:c.find("=")])
- CtgPatt = [Pattern(c) for c in BP.CategName]
-
- DoIndexCategs()
- Acc = BP.AccountCurrent()
- l, b, a, cc = "TLabel", "TButton", ["akBottom", "akRight"], CreateComponent
- DtFmts = ["JMA", "MJA", "AMJ"]
- FDup = cc("TForm", None)
- FDup.SetProps(Width=400, Height=390, Position="poMainFormCenter", BorderStyle="bsSingle", BorderIcons=["biSystemMenu"], Caption="DΘtection de doublons")
- l0 = cc(l, FDup)
- l0.SetProps(Parent=FDup, Left=20, Top=20)
- l1 = cc(l, FDup)
- l1.SetProps(Parent=FDup, Left=20, Top=60, Caption="Ligne α insΘrer :")
- l2 = cc(l, FDup)
- l2.SetProps(Parent=FDup, Left=20, Top=190, Caption="Ligne existante :")
- l0.Font.Style = l1.Font.Style = l2.Font.Style = ["fsBold"]
- cc(l, FDup).SetProps(Parent=FDup, Left=40, Top=80, Caption="Date :")
- cc(l, FDup).SetProps(Parent=FDup, Left=40, Top=100, Caption="Mode :")
- cc(l, FDup).SetProps(Parent=FDup, Left=40, Top=120, Caption="Tiers :")
- cc(l, FDup).SetProps(Parent=FDup, Left=40, Top=140, Caption="DΘtails :")
- cc(l, FDup).SetProps(Parent=FDup, Left=40, Top=160, Caption="Montant :")
- cc(l, FDup).SetProps(Parent=FDup, Left=40, Top=210, Caption="Date :")
- cc(l, FDup).SetProps(Parent=FDup, Left=40, Top=230, Caption="Mode :")
- cc(l, FDup).SetProps(Parent=FDup, Left=40, Top=250, Caption="Tiers :")
- cc(l, FDup).SetProps(Parent=FDup, Left=40, Top=270, Caption="DΘtails :")
- cc(l, FDup).SetProps(Parent=FDup, Left=40, Top=290, Caption="Montant :")
- lD = cc(l, FDup)
- lD.SetProps(Parent=FDup, Left=120, Top=80)
- lM = cc(l, FDup)
- lM.SetProps(Parent=FDup, Left=120, Top=100)
- lT = cc(l, FDup)
- lT.SetProps(Parent=FDup, Left=120, Top=120)
- lI = cc(l, FDup)
- lI.SetProps(Parent=FDup, Left=120, Top=140)
- lA = cc(l, FDup)
- lA.SetProps(Parent=FDup, Left=120, Top=160)
- LD = cc(l, FDup)
- LD.SetProps(Parent=FDup, Left=120, Top=210)
- LM = cc(l, FDup)
- LM.SetProps(Parent=FDup, Left=120, Top=230)
- LT = cc(l, FDup)
- LT.SetProps(Parent=FDup, Left=120, Top=250)
- LI = cc(l, FDup)
- LI.SetProps(Parent=FDup, Left=120, Top=270)
- LA = cc(l, FDup)
- LA.SetProps(Parent=FDup, Left=120, Top=290)
- lD.Font.Color = lM.Font.Color = lT.Font.Color = lI.Font.Color = lA.Font.Color = LD.Font.Color = LM.Font.Color = LT.Font.Color = LI.Font.Color = LA.Font.Color = 0x00CC0000
- cc(b, FDup).SetProps(Parent=FDup, Left=40, Top=320, Width=75, Height=25, Caption="Oui", ModalResult=6)
- cc(b, FDup).SetProps(Parent=FDup, Left=120, Top=320, Width=75, Height=25, Caption="Non", ModalResult=7)
- cc(b, FDup).SetProps(Parent=FDup, Left=200, Top=320, Width=75, Height=25, Caption="Toutes", ModalResult=10)
- cc(b, FDup).SetProps(Parent=FDup, Left=280, Top=320, Width=75, Height=25, Caption="Aucune", ModalResult=9)
-
- def CheckPos(Sender):
- CCtgs.Top = F0.Height - 70
-
- F0 = cc("TForm", None)
- F0.SetProps(Position = "poMainFormCenter", Width=600, Height=320, Caption = "ParamΦtres de l'import", OnShow=CheckPos)
- F0.Constraints.MinWidth = 600
- cc(l, F0).SetProps(Parent=F0, Left=16, Top=20, Caption="Sens de la date :")
- cc(l, F0).SetProps(Parent=F0, Left=160, Top=20, Caption="Doublons :")
- cc(l, F0).SetProps(Parent=F0, Left=276, Top=20, Caption="Contenu du fichier :")
- CBDate = cc("TComboBox", F0)
- CBDate.SetProps(Parent=F0, Left=16, Top=39, Width=93, Style="csDropDownList")
- CBDate.Items.Text = "\n".join(DtFmts)
- CBDate.ItemIndex = 0
- CBDup = cc("TComboBox", F0)
- CBDup.SetProps(Parent=F0, Left=160, Top=39, Width=100, Style="csDropDownList")
- CBDup.Items.Text = "Tout accepter\nTout refuser\nDemander"
- CBDup.ItemIndex = 2
- Memo = cc("TMemo", F0)
- Memo.SetProps(Parent=F0, Left=276, Top=40, Width=293, Height=89, WordWrap=1, Anchors=a+["akTop","akLeft"])
- CCtgs = cc("TCheckBox", F0)
- CCtgs.SetProps(Parent=F0, Left=16, Top=300, Width=213, Caption="CrΘer les catΘgories manquantes", Anchors=["akLeft", "akBottom"])
- BKO = cc(b, F0)
- BKO.SetProps(Parent=F0, Left=415, Top=300, Width=75, Height=25, Caption="Annuler", ModalResult=2, Cancel=1, Anchors=a)
- BOK = cc(b, F0)
- BOK.SetProps(Parent=F0, Left=495, Top=300, Width=75, Height=25, Caption="Suivant >>", ModalResult=1, Default=1, Anchors=a)
-
- FF = cc("TForm", None)
- FF.SetProps(Width=640, Height=450, Position="poMainFormCenter", BorderStyle="bsSingle", BorderIcons=["biSystemMenu"], Caption="RΘsultat de l'import")
- cc(b, FF).SetProps(Parent=FF, Left=270, Top=370, Width=100, Height=25, Caption="Fermer", ModalResult=1, Cancel=1, Default=1)
- MRes = cc("TMemo", FF)
- MRes.SetProps(Parent=FF, Left=30, Top=30, Width=580, Height=350, Anchors=["akTop","akLeft", "akRight", "akBottom"], WordWrap=0, Readonly=1)
-
- FF.Font.Name = F0.Font.Name = FDup.Font.Name = "Tahoma"
-
- def GetCtg(s):
- if s.strip() == "": return -1
- t = Pattern(s)
- if t.strip() == "": return -1
- if t in CtgPatt: return CIndexes.get(CtgPatt.index(t), -1)
-
- for i in range(len(CtgPatt)):
- c = CtgPatt[i]
- if t in c or c in t: return CIndexes.get(i, -1)
-
- if CCtgs.Checked:
- BP.CategAdd(s, 0)
- DoIndexCategs()
- return CIndexes.get(BP.CategCount() - 1, -1)
- return -1
-
- def getmode(s, sign):
- s = s.strip()
- if s != "":
- if sign == -1 and s.isdigit(): return "Chq %s" %s
-
- v = Pattern(s)
- if sign == 1: fmodes = {"Versement": ["vers", "esp"], "DΘp⌠t de chΦque": ["rem", "dep", "ch"], "Virement reτu": ["vir", "vrm", "vrt"]}
- else: fmodes = {"Carte": ["fac", "cb", "car"], "Retrait DAB": ["ret", "dab", "distrib", "automat"], "ChΦque Θmis": ["ch"], "PrΘlΦvement": ["pr"], "Virement Θmis": ["vir", "vrm", "vrt"], "TIP": ["tip"]}
-
- for m in fmodes.keys():
- fpatterns = fmodes[m]
- for fpattern in fpatterns:
- if v.find(fpattern) == 0:
- if m == "ChΦque Θmis":
- v = s.split(" ")[-1].split(".")[-1].split("░")[-1].split("Q")[-1].split("E")[-1].split("H")[-1]
- if v.isdigit(): return "Chq %s" %v
- return m
- if sign == 1: return "Virement reτu"
- return "PrΘlΦvement"
-
- def getprefixes(L):
- d = {}
- for l in L:
- if len(l) > 0 and l[0] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
- d[l[0]] = 1
- r = d.keys()
- r.sort()
- return r
-
- def AddCombos(prefixes):
- c = "\n".join(["--------", "Date", "Mode", "Tiers", "DΘtails", "CatΘgorie", "Montant"])
- f = []
- for i, p in enumerate(prefixes):
- top = 84 + i * 26
- cc("TLabel", F0).SetProps(Parent=F0, Left=16, Top=top+4, Caption="La lettre %s prΘcΦde le champ" %p)
- cb = cc("TComboBox", F0)
- cb.SetProps(Parent=F0, Left=160, Top=top, Width=100, Style="csDropDownList")
- cb.Items.Text = c
- cb.ItemIndex = "DNPMLT".find(p) + 1
- f.append(cb)
- return f
-
- def strtodate(d):
- seps = "/-' .;"
- d = d.replace("-", "/").replace(".", "/").replace("'", "/").replace(" ", "").split("/")
- if len(d) != 3 or not "".join(d).isdigit(): return None
- d = [int(d[0]), int(d[1]), int(d[2])]
- if DtFmt == "JMA": return (d[2], d[1], d[0])
- elif DtFmt == "MJA": return (d[2], d[0], d[1])
- elif DtFmt == "AMJ": return (d[0], d[1], d[2])
- elif DtFmt == "AJM": return (d[0], d[2], d[1])
- else: return None
-
- def strtofloat(s):
- s = s.replace("$", "").replace(" ", "").replace("Ç", "").replace("F", "").replace(",", ".")
- if "." in s:
- l = s.split(".")
- s = "%s.%s" %( "".join(l[:-1]), l[-1] )
- try:
- f = float(s)
- except:
- return None
- return f
-
- def linestodic(lines, mapping):
- fields = ["Date", "Mode", "Tiers", "DΘtails", "CatΘgorie", "Montant"]
- result = {}
- sgn = 0
- for line in lines:
- i = mapping[line[0]]
- if i > 0:
- field = fields[i - 1]
- value = line[1:]
- if field == "Date":
- value = strtodate(value)
- if value is None: return None
- elif field == "CatΘgorie": value = GetCtg(value)
- elif field == "Montant":
- value = strtofloat(value)
- if value == None: return None
- if value > 0: sgn = 1
- elif value < 0: sgn = -1
- result[field] = value
- try:
- if sgn != 0: result["Mode"] = getmode(result.get("Mode", ""), sgn)
- except:
- pass
- return result
-
- def divide(lines, mapping):
- res = []
- MinDate = (3000, 12, 31)
- rep = {"OpΘrations importΘes" : [], "Dates incorrectes" : [], "Montants incorrects" : [], "Enregistrements incorrects" : [], "Lignes refusΘes" : [], "Doublons" : []}
- while lines.count("^") > 0:
- i = lines.index("^")
- r = linestodic(lines[:i], mapping)
- if r != None:
- if not r.has_key("Date"): rep["Dates incorrectes"].append(", ".join(lines[:i]))
- elif not r.has_key("Montant"): rep["Montants incorrects"].append(", ".join(lines[:i]))
- else:
- y, m, d = r["Date"]
- if y < 100: y += 2000
- r["Date"] = (y, m, d)
- if (y, m, d) < MinDate: MinDate = (y, m, d)
- res.append(r)
- else: rep["Enregistrements incorrects"].append(", ".join(lines[:i]))
- del lines[:i + 1]
- return res, rep, MinDate
-
- def FlatCheck(m, t, i):
- if m == "ChΦque Θmis" and i != "":
- num = t.split("░")[-1].split(" ")[-1]
- if num.isdigit(): m = "Chq %s" %num
- else:
- num = i.split("░")[-1].split(" ")[-1]
- if num.isdigit(): m = "Chq %s" %num
-
- if m.find("Chq ") == 0:
- if i == "": i = "n░%s" %(m[4:])
- else: i = "n░%s %s" %(m[4:], i)
- m = "ChΦque Θmis"
-
- return m, t, i
-
- def ReportErrors(R):
- ok = 0
- ko = 0
- L = []
- for key in R.keys():
- l = R[key]
- num = len(l)
- if num == 0: continue
- if key == "OpΘrations importΘes": ok += num
- else: ko += num
- l = [" %s" %s for s in l]
- L.append("%s (%d) :\r\n\r\n%s" %(key, num, "\r\n".join(l)))
-
- T = ok + ko
- if T == 0:
- s = "Il n'y a aucune ligne α importer depuis le fichier"
- else:
- if ko == 0:
- if T == 1: s = "L'opΘration contenue dans le fichier QIF a ΘtΘ importΘe sans erreurs"
- else: s = "Les %d opΘrations contenues dans le fichier QIF ont ΘtΘ importΘes sans erreurs" %T
- elif ok == 0: s = "Aucune ligne n'a pu Ωtre importΘe"
- else:
- if ok == 1: s = "Une opΘration sur %d a ΘtΘ importΘe" %(T)
- else: s = "%d opΘrations sur %d ont ΘtΘ importΘes" %(ok, T)
-
- s = "%s\r\n\r\n%s" %(s, "\r\n\r\n".join(L))
- return s
-
- def IsDate(t):
- try:
- y, m, d = t
- if (m == 2) and (y % 4 == 0) and ( (y % 100 != 0) or (y % 400 == 0) ): Max = 29
- else: Max = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][m - 1]
- return m > 0 and m < 13 and d > 0 and d <= Max
- except:
- return 0
-
- def FormatLine(dic):
- s = []
- for key in dic:
- v = dic[key]
- if key == "Date": v = datetostr(v)
- s.append("%s : %s" %(key, v))
- s.sort()
- return ", ".join(s)
-
- def datetostr(d):
- y, m, d = d
- if y < 100: y += 2000
- return "%02d/%02d/%04d" %(d, m, y)
-
- def TestDup(N, T, Rep, ask, Lines, Light, R, d, m, v):
- if ask == 0: res = "ok", ask
- elif not (d, m, v) in Light: res = "ok", ask
- elif ask == 1: res = "ko", ask
- else:
- i = Light.index((d, m, v))
- l = Lines[i]
- lD.Caption, lM.Caption, lT.Caption, lI.Caption, lA.Caption = datetostr(R[0]), R[1], R[2], R[3], R[4]
- LD.Caption, LM.Caption, LT.Caption, LI.Caption, LA.Caption = datetostr(l[0]), l[1], l[3], l[4], l[2]
- l0.Caption = "La ligne %d/%d ressemble α une ligne existante.\nSouhaitez-vous l'insΘrer ?" %(N, T)
- i = FDup.ShowModal()
- res = {2: ("ko", ask), 6: ("ok", ask), 10: ("ok", 0), 7: ("ko", ask), 9: ("ko", 1)}[i]
-
- if res[0] == "ko": Rep["Doublons"].append(line)
- return res
-
- def simplecheck(s):
- return [s, "ChΦque Θmis"][s.find("Chq") == 0]
-
- def GetLines(From):
- l1 = zip(BP.OperationDate[Acc], BP.OperationMode[Acc], BP.OperationAmount[Acc], BP.Operationthirdparty[Acc], BP.OperationDetails[Acc])
- l1 = [((int(d[6:10]), int(d[3:5]), int(d[0:2])), m, v, w, i) for (d, m, v, w, i) in l1 if (int(d[6:10]), int(d[3:5]), int(d[0:2])) >= From]
- l2 = [(l[0], simplecheck(l[1]), l[2]) for l in l1]
- return l1, l2
-
-
-
- QIFFile = BP.OpenDialog("Choisissez le fichier α importer", "\\", ".qif", "Quicken Interchange Format (*.QIF)|*.qif")
- if QIFFile != "":
- f = open(QIFFile).readlines()
- f = [l.replace("\n", "").strip() for l in f if len(l) > 0 and l[0] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ^"]
- prefixes = getprefixes(f)
- if len(prefixes) < 3: BP.MsgBox("Le fichier n'est pas un fichier QIF correct", 0)
- else:
- BP.AccountRefreshScreen()
- h = 160 + 26 * len(prefixes)
- Combos = AddCombos(prefixes)
- Memo.Height, Memo.Lines.Text = h - 121, "\n".join(f[:50])
- CCtgs.Top = BKO.Top = BOK.Top = h - 69
- F0.Height = F0.Constraints.MinHeight = h
- Memo.Height = h - 120
- BOK.Top = h - 70
- BKO.Top = h - 70
- if F0.ShowModal() == 1:
- dupl, DtFmt = CBDup.ItemIndex, DtFmts[CBDate.ItemIndex]
- mapping = dict([(p, Combos[i].ItemIndex) for i, p in enumerate(prefixes)])
- operations, report, MinDate = divide(f, mapping)
- CurrLines, LinesLight = GetLines(MinDate)
- i, num_ok, count_op = 0, 0, len(operations)
- for op in operations:
- line, i = FormatLine(op), i + 1
- date, mode, tier, info, catg, mont = op.get("Date", ""), op.get("Mode", ""), op.get("Tiers", ""), op.get("DΘtails", ""), op.get("CatΘgorie", ""), op.get("Montant", "")
- if not IsDate(date): report["Dates incorrectes"].append(line)
- elif mont == "" or abs(mont) < 0.0001: report["Montants incorrects"].append(line)
- else:
- InsDup, dupl = TestDup(i, count_op, report, dupl, CurrLines, LinesLight, (date, mode, tier, info, mont), date, simplecheck(mode), mont)
- if InsDup == "ko": continue
- if catg == "": catg = -1
- mode, tier, info = FlatCheck(mode, tier, info)
- count1, date = BP.OperationCount[Acc], datetostr(date)
- BP.LineAdd(Acc, date, mode, tier, info, catg, mont, 0)
- count2 = BP.OperationCount[Acc]
- if count2 == count1: report["Lignes refusΘes"].append(line)
- else: report["OpΘrations importΘes"].append(line)
-
- BP.AccountRefreshScreen()
- MRes.Lines.Text = ReportErrors(report)
- FF.ShowModal()